package audi.server;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Logger;

import org.json.simple.JSONObject;

import audi.json.GetJson;
import audi.model.GetTag;
import audi.model.LocalData;
import audi.model.OJChangepass;
import audi.model.OJLogin;
import audi.model.OJResponsive;
public class StartServer implements Runnable {
	 private static Logger logtag = Logger.getLogger(StartServer.class.getName());
	// commands:
	// .q quit
	// .w who
	// Variables for each thread
	Socket linkto; // the socket
	PrintWriter out; // the output and input streams
	BufferedReader in;
	int id; // i.d. of the connection
	String outline;
	String from_name; // name of host connecting
	String group;
	Boolean box;
	Map<String, String> ipgroup = new HashMap<>();

	// Class Variables

	static Vector connectiontable; // current connections
	static int nextid = 1; // Increasing i.d.

	// ///////////////////////////// Main method ////////////////////////

	public static void main(String[] args) {
		// Parent thread - create a server socket and await a connection
		ServerSocket ss = null;
		Socket s = null;
		connectiontable = new Vector();

		try {
			ss = new ServerSocket(11008);
			while ((s = ss.accept()) != null) {
				System.out.println("Receiving...");
				// Connection received - create a thread
				StartServer now;
				Thread current = new Thread(now = new StartServer(s));
				current.setDaemon(true);
				connectiontable.addElement(now); // Save talker into vector ..
				current.start(); // start the user's thread
			}
		} catch (Exception e) {
			System.out.println(e);
		}

		// should add finally block to close down
	}

	// /////////////// Constructor for a new thread //////////////////////

	StartServer(Socket from) {
		id = nextid++;
		linkto = from;
		
		InetAddress source = linkto.getInetAddress();
		from_name = source.getHostAddress();
		group = source.getHostName();
		
//		ipgroup.put("groupdd"+id,from_name);
		try {
			out = new PrintWriter(new OutputStreamWriter(
					linkto.getOutputStream()));
			in = new BufferedReader(new InputStreamReader(
					linkto.getInputStream()));
			System.out.println("Connected");
		} catch (Exception e) {
		}
	}

	public void run() {
//		String line = " Wellcome <" +id +">";
		String line = "";
		System.out.println("Success connect with client id: "+ id);
		while (true) {
			boolean done = false;

			// read a line from the user

			if (line == null) {
				try {
					out.print(""); // prompt,flush,read
					out.flush();
					line = in.readLine();
					System.out.println("Receiver string = "+line);
				} catch (Exception e) {
					System.out.println(e);
					done = true; // force exit if there's a problem
				}
			}
			
			try {
				if (line.startsWith(".q"))
					done = true;
			} catch (Exception e) { // e.g. null
				done = true;
				line = "[exiting]";
			}
			
			if (line.startsWith(".w")) { // build up list of host names
				int k;
				StringBuffer fred = new StringBuffer("WHO HERE?\n");
				for (k = 0; k < connectiontable.size(); k++) {
				
					StartServer person = (StartServer) connectiontable.elementAt(k);
					fred.append(person.from_name + "---Group: " + person.group);
					fred.append(" ");
				}
				line = fred.toString();
			}	
			if (line.startsWith(".g"))
			{
				setgroup(line);
			}
			if (line.startsWith(".s")) { // send only group
				int k;
				logtag.info("\nBắt đầu send theo group:");
				for (k = 0; k < connectiontable.size(); k++) {
					try{
					StartServer person = (StartServer) connectiontable.elementAt(k);
					String[] parts = line.split("-");
					String part1 = parts[1];
					String part2 = parts[2];
					logtag.info("\ngroup của user này là:"+part1 + "tên group là: "+person.group);
//					person.group = line;
//					logtag.info("\nSet group cho:"+k);
					if (person.group.equals(part1))
					{	
						logtag.info("\nbắt đầu send");
						returntoclient(person.group, part2);
					}
					}
					catch(Exception e)
					{
						logtag.info("\nlỗi khi seend group:"+e);
					}
				}
			}
			/*
			 * Check whats tag
			 */
			GetJson mgetjson = new GetJson();
			GetTag mgetTag = new GetTag();	
			try {	
				mgetTag=null;
				mgetTag = mgetjson.getTag(line);
				try{
				if (mgetTag.getGroup()!=null)
					{
					setgroup(mgetTag.getGroup());
					logtag.info("\nGroup của user này là: "+ mgetTag.getGroup());
					}					
				else {
					setgroup(from_name);
					logtag.info("\nGroup của user này là: "+ from_name);
				}
				if (mgetTag.getBox()==true)
				{
					setbox(true);
				}
				}
				catch (Exception e)
				{
					logtag.info("\n Lỗi khi set group:  "+e);
				}
				
				if (mgetTag.getTag().equals("login"))
				{	
					logtag.info("\nTag login");
					line = requestlogin(mgetjson,mgetTag);					
				}
				if (mgetTag.getTag().equals(LocalData.TAG_REGISTER))
				{	
					logtag.info("\nTag Register");			
					line = requestregister(mgetjson, mgetTag);
				
				}
				if (mgetTag.getTag().equals(LocalData.TAG_STATUS))
				{	
					logtag.info("\n---------------Tag status");
					Boolean checkbox = checkbox();
					if (checkbox==true)
					{
						line = mgetTag.getJson();
						logtag.info("\n CHECKBOX = TRUE");
					}
					
					else 
					{
						logtag.info("\n CHECKBOX = FALSE");
						JSONObject mJSONObject = new JSONObject();
						mJSONObject.put(LocalData.TAG, LocalData.TAG_CHECKBOX);
						mJSONObject.put(LocalData.TAG_SUCCESS, false); 
						mJSONObject.put("mess", "Box Android hiện không kết nối vào Server");
						line = mJSONObject.toString();
						
					}
					logtag.info("\n Return string: " + line);
				}
				if (mgetTag.getTag().equals(LocalData.TAG_CHANGEPASS))
				{	
					line = requestchangepass(mgetjson, mgetTag);
					logtag.info("\nTag TAG change pass");
//					line = mgetTag.getJson();
				}
					if (mgetTag.getGroup()!=null) returntoclient(mgetTag.getGroup(),line);
					else returntoclient(from_name,line);
			}
			catch (Exception e)
			{
				logtag.info("\n Lỗi khi parse:  "+ e);				
			}
			
			/*
			 * send to client
			 */
//			outline = line;
//			int k;
//			for (k = 0; k < connectiontable.size(); k++) {
//				StartServer person = (StartServer) connectiontable.elementAt(k);
//				try{
//				if (person.group.equals(".gtest"))
//				{	
//					person.out.println(outline);
//					person.out.flush(); // Vital - ensure it is sent!
//					System.out.println("\nTên:" + person.from_name + "thuộc nhóm: .gtest");
//				}
////				else
////				{
////					logtag.info("\nKhông cùng nhóm:");	
////					return;
////				}
//			}
//				catch(Exception e)
//				{
//					logtag.info("\nLỗi khi xét if:"+e);	
//				}
//			
//			}
				
			// clear out the user if they're done
			if (done) {
				connectiontable.removeElement(this);
				try {
					out.close(); // closes needed to terminate connection
					in.close(); // otherwise user's window goes mute
					linkto.close();
				} catch (Exception e) {
				}
				break;
			}
			line = null;
		}
	}
	
	String requestlogin (GetJson mgetjson,GetTag mgetTag )
	{	
//		OJResponsive mOJResponsive = new OJResponsive();
		JSONObject jsreturn = new JSONObject();
		JSONObject jsauthen = new JSONObject();
	WebHelper mWebHelper = new WebHelper();
	OJLogin mOJLogin2 = new OJLogin(); // biến trả về
		try{			
			OJLogin mOJLogin = new OJLogin();
			mOJLogin = mgetjson.getlogin(mgetTag.getJson());
			System.out.print("\nResult request login: "+ mOJLogin.getUsername() + ";"+ mOJLogin.getPassword());
			mOJLogin2 = mWebHelper.Login(mOJLogin.getUsername(),mOJLogin.getPassword());	
//			logtag.info("Username:"+mOJLogin2.getResult()+"|"+
//					mOJLogin2.getMess()+"|"+
//					mOJLogin2.getEmail()+"|"+
//					mOJLogin2.getUsername()+"|"+
//					mOJLogin2.getIssuccess()+"|"+
//					mOJLogin2.getGroup());
			
			try{
			jsauthen.put(LocalData.TAG_USERGROUP, mOJLogin2.getGroup());
			jsauthen.put(LocalData.TAG_USERNAME,mOJLogin2.getEmail());
			jsreturn.put(LocalData.TAG, LocalData.TAG_LOGIN);
			jsreturn.put(LocalData.TAG_SUCCESS, mOJLogin2.getIssuccess());
			jsreturn.putAll(jsauthen);
			}
			catch(Exception e)
			{
				jsreturn.put("Tag", "login");
				jsreturn.put("success", false);
			}
			logtag.info("json return"+jsreturn.toString());
				}
		catch(Exception e)
		{
			System.out.print("\n Failed when get parse login info: " + e);
		}
		return jsreturn.toString();
	}
	/*
	 * return register string
	 */
	String requestregister (GetJson mgetjson,GetTag mgetTag )
	{	
//		OJResponsive mOJResponsive = new OJResponsive();
		JSONObject jsreturn = new JSONObject();
		JSONObject jsauthen = new JSONObject();
	WebHelper mWebHelper = new WebHelper();
	OJLogin mOJLogin2 = new OJLogin(); // biến trả về
		try{			
			OJLogin mOJLogin = new OJLogin();
			mOJLogin = mgetjson.getlogin(mgetTag.getJson());
			System.out.print("\nResult request login: "+ mOJLogin.getUsername() + ";"+ mOJLogin.getPassword());
			mOJLogin2 = mWebHelper.Register(mOJLogin.getUsername(), mOJLogin.getPassword(), mOJLogin.getGroup());	
//			logtag.info("Username:"+mOJLogin2.getResult()+"|"+
//					mOJLogin2.getMess()+"|"+
//					mOJLogin2.getEmail()+"|"+
//					mOJLogin2.getUsername()+"|"+
//					mOJLogin2.getIssuccess()+"|"+
//					mOJLogin2.getGroup());
			
			try{
			jsauthen.put(LocalData.TAG_USERGROUP, mOJLogin2.getGroup());
			jsauthen.put(LocalData.TAG_USERNAME,mOJLogin2.getEmail());
			jsreturn.put(LocalData.TAG, LocalData.TAG_REGISTER);
			jsreturn.put(LocalData.TAG_SUCCESS, mOJLogin2.getIssuccess());
			jsreturn.putAll(jsauthen);
			}
			catch(Exception e)
			{
				jsreturn.put("Tag", LocalData.TAG_REGISTER);
				jsreturn.put("success", false);
			}
			logtag.info("json return"+jsreturn.toString());
				}
		catch(Exception e)
		{
			System.out.print("\n Failed when get parse login info: " + e);
		}
		return jsreturn.toString();
	}
	/*
	 * Change pass
	 */
	String requestchangepass (GetJson mgetjson,GetTag mgetTag )
	{	
//		OJResponsive mOJResponsive = new OJResponsive();
		JSONObject jsreturn = new JSONObject();
		JSONObject jsauthen = new JSONObject();
	WebHelper mWebHelper = new WebHelper();
	OJChangepass mOJLogin2 = new OJChangepass(); // biến trả về
		try{			
			OJChangepass mOJChangepass = new OJChangepass();
			mOJChangepass = mgetjson.getchangepass(mgetTag.getJson());
			System.out.print("\nResult request login: "+ mOJChangepass.getUsername() + ";"+ mOJChangepass.getOldpass() + mOJChangepass.getMess());
			mOJLogin2 = mWebHelper.Changepass(mOJChangepass.getUsername(), mOJChangepass.getOldpass(),mOJChangepass.getNewpass() );	
			try{
//			jsauthen.put(LocalData.TAG_USERGROUP, mOJLogin2.getGroup());
//			jsauthen.put(LocalData.TAG_USERNAME,mOJLogin2.getEmail());
			jsreturn.put(LocalData.TAG, LocalData.TAG_CHANGEPASS);
			jsreturn.put(LocalData.TAG_SUCCESS, mOJLogin2.getIssuccess());
			jsreturn.putAll(jsauthen);
			}
			catch(Exception e)
			{
				jsreturn.put("Tag", LocalData.TAG_REGISTER);
				jsreturn.put("success", false);
			}
			logtag.info("json return"+jsreturn.toString());
				}
		catch(Exception e)
		{
			System.out.print("\n Failed when get parse login info: " + e);
		}
		return jsreturn.toString();
	}
	/*
	 * send satus
	 */
	String sendstatus (GetJson mgetjson,GetTag mgetTag) 
	{
		
		return from_name;
		
	}
	/*
	 * Send return
	 */
	void returntoclient (String mgroup, String strreturn)
	{	int k;
		for (k = 0; k < connectiontable.size(); k++) {
			StartServer person = (StartServer) connectiontable.elementAt(k);
			try{
			if (person.group.equals(mgroup))
			{	
				person.out.println(strreturn);
				person.out.flush(); // Vital - ensure it is sent!
				System.out.println("\nTên:" + person.from_name + "thuộc nhóm:" + mgroup);
			}
//			else
//			{
//				logtag.info("\nKhông cùng nhóm:");	
//				return;
//			}
		}
			catch(Exception e)
			{
				logtag.info("\nLỗi khi xét if:"+e);	
			}
		
		}
	}
	/*
	 * set group for client
	 */
	void setgroup (String group)
	{
		 // test send by group
		int k;
		for (k = 0; k < connectiontable.size(); k++) {
			try{
			StartServer person = (StartServer) connectiontable.elementAt(k);
			InetAddress source = linkto.getInetAddress();
			if (person.from_name.equals(source.getHostAddress()) )
			{
			person.group = group;
			logtag.info("\nSet :"+k+" vào group " + group +" thành công.");
			}
			else
			logtag.info("\nChưa set được"+person.from_name +" và: "+source.getHostAddress());
			}
			catch(Exception e)
			{
				logtag.info("\nlỗi khi set group:"+e);
			}
		}
	
	}
	void setbox (Boolean box)
	{
		 // test send by group
		int k;
		for (k = 0; k < connectiontable.size(); k++) {
			try{
			StartServer person = (StartServer) connectiontable.elementAt(k);
			InetAddress source = linkto.getInetAddress();
			if (person.from_name.equals(source.getHostAddress()) )
			{
			person.box = box;
			logtag.info("\nSet :"+k+" vào group " + group +" thành công.");
			}
			else
			logtag.info("\nChưa set được"+person.from_name +" và: "+source.getHostAddress());
			}
			catch(Exception e)
			{
				logtag.info("\nlỗi khi set group:"+e);
			}
		}
	
	}
	Boolean checkbox()
	{
		Boolean result =false;
			 // test send by group
			int k;
			for (k = 0; k < connectiontable.size(); k++) {
				try{
				StartServer person = (StartServer) connectiontable.elementAt(k);
				if (person.box.equals(true) )
				{
					result = true;
				logtag.info("\nCó box connect vào server");
				}
				else
				{
				logtag.info("\nKhông có box connect vào server");
				result = false;
				}
				}
				catch(Exception e)
				{
					logtag.info("\nlỗi khi set group:"+e);
				}
			}
		
		return result;
	}
}